#include "stdafx.h"

#include "MyControls/WireTool.h"	  
#include <MyViews/ZoomBench.h>

namespace My {

WireTool::WireTool(ZoomBench & owner)
	: m_Owner(owner)
{
	m_Control = false;
	m_MouseState = ButtonsUp;
	VERIFY (m_CursorCross = AfxGetApp()->LoadCursor("CROSS"));
	m_WireWidth = 1;
	m_WireVisible = false;
	m_ShowWire = true;
	m_Hidden = false;
	m_SizingRate = 0;
}

BEGIN_MESSAGE_MAP(WireTool, CCmdTarget)
	//{{AFX_MSG_MAP(WireTool)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

const CPoint WireTool::GetPosition()
{
	CPoint p;
	GetCursorPos(&p);
	GetBench().ScreenToClient(&p);
	return p;
}

bool WireTool::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
	SetCursor(m_CursorCross);
	return true;
}

void WireTool::Activate()
{
	Show();
}

void WireTool::Deactivate()
{
	Hide();
}

void WireTool::ShowWire(CDC * pDC)
{
	if (m_WireVisible || !m_ShowWire || m_Hidden)
		return;

	DrawWire(pDC, m_DrawnWirePosition = GetPosition(), m_WireWidth = m_Control ? 2 : 1);
	m_WireVisible = true;
}

void WireTool::ShowWire()
{
	CClientDC dc(&GetBench());
	ShowWire(&dc);
}

void WireTool::HideWire(CDC * pDC)
{
	if (!m_WireVisible || !m_ShowWire || m_Hidden)
		return;

	DrawWire(pDC, m_DrawnWirePosition, m_WireWidth);
	m_WireVisible = false;
}

void WireTool::HideWire()
{
	if (GetBench().m_hWnd == 0) //this may happen if HideWire() is called from dtor, then Bench's window no longer exists
		return;
	CClientDC dc(&GetBench());
	HideWire(&dc);
}

void WireTool::Show()
{
	m_ShowWire = GetBench().IsInside();
	m_Hidden = false;
	ShowWire();
}

void WireTool::Hide()
{
	HideWire();
	m_MouseState = ButtonsUp;
	m_Control = false;
	m_ShowWire = false;
	m_Hidden = true;
	m_WireVisible = false;
}

void WireTool::PaintRect(CDC * pDC, const CRect & r)
{
	if (m_WireVisible)
		DrawWire(pDC, m_DrawnWirePosition, m_WireWidth);
}

void WireTool::RedrawWire()
{
	CClientDC dc(&GetBench());
	HideWire(&dc);
	ShowWire(&dc);
}

void WireTool::Apply(CPoint p)
{
	GetBench().InvalidateRect(GetWireRect(p));
	Select(p, m_MouseState);
	GetBench().UpdateWindow();
}

void WireTool::OnLButtonDown(UINT nFlags, CPoint p)
{
	if (m_Control) {
		IncreaseSize(1);
		return;
	}
	GetBench().SetCapture();
	m_MouseState |= LButtonDown;
	Apply(p);
}

void WireTool::OnLButtonDblClk(UINT nFlags, CPoint p) 
{
	//treat second click in double click as second click :)
	OnLButtonDown(nFlags, p);
}

void WireTool::OnRButtonDblClk(UINT nFlags, CPoint p) 
{
	OnRButtonDown(nFlags, p);
}

void WireTool::OnRButtonDown(UINT nFlags, CPoint p)
{
	if (m_Control) {
		IncreaseSize(-1);
		return;
	}
	GetBench().SetCapture();
	m_MouseState |= RButtonDown;
	Apply(p);
}

void WireTool::OnMouseMove(UINT, CPoint p)
{
	if (m_MouseState != ButtonsUp) {
		GetBench().InvalidateRect(GetWireRect(m_DrawnWirePosition));
		Apply(m_DrawnWirePosition = p);
	}
	else {
		if (m_ShowWire && m_WireVisible && !m_Hidden)
			RedrawWire();
	}
}

void WireTool::OnMouseEnter(UINT, CPoint p)
{
	m_ShowWire = true;
	ShowWire();
}

void WireTool::OnMouseLeave()
{
	HideWire();
	m_ShowWire = false;
	if (m_MouseState != ButtonsUp) {
		m_MouseState = ButtonsUp;
		ReleaseCapture();
		Synchronize();
	}
}

void WireTool::OnLButtonUp(UINT nFlags, CPoint p)
{
	if ((m_MouseState & LButtonDown) == 0)
		return; //it happends e.g. after pressing mouse button to focus on the view
	m_MouseState &= ~LButtonDown;
	if (m_MouseState == ButtonsUp) {
		ReleaseCapture();
		Synchronize();
	}
	else
		Apply(p);
}

void WireTool::OnRButtonUp(UINT nFlags, CPoint p)
{
	if ((m_MouseState & RButtonDown) == 0)
		return; //it happends e.g. after pressing mouse button to focus on the view
	m_MouseState &= ~RButtonDown;
	if (m_MouseState == ButtonsUp) {
		ReleaseCapture();
		Synchronize();
	} else
		Apply(p);
}

void WireTool::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	switch (nChar) 
	{ 
	case VK_MENU:
		if (!m_Control) {
			HideWire();
			m_Control = true;
			ShowWire();
		}
		break;
	case VK_ADD:
		if (m_Control) {
	case VK_OEM_6: //']'
			m_SizingRate++;
			int inc = 1;
			if (m_SizingRate > 1)
				inc = 2;
			if (m_SizingRate > 3)
				inc = 5;
			if (m_SizingRate > 5)
				inc = 10;
			IncreaseSize(inc);
		}
		break;
	case VK_SUBTRACT:
		if (m_Control) {
	case VK_OEM_4: //'['
			m_SizingRate++;
			int inc = 1;
			if (m_SizingRate > 1)
				inc = 2;
			if (m_SizingRate > 3)
				inc = 5;
			if (m_SizingRate > 5)
				inc = 10;
			IncreaseSize(-inc);
		}
		break;
	}
}

void WireTool::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
{
	m_SizingRate = 0;

	if (nChar == VK_MENU) {
		if (m_Control) {
			HideWire();
			m_Control = false;
			ShowWire();
		}
	}
}

} //namespace My
